<?php
// chat_server.php
use Workerman\Timer;
use Workerman\Worker;

require_once 'vendor/autoload.php';

// 创建一个 WebSocket 服务
$ws_worker = new Worker("websocket://0.0.0.0:8282"); // 监听端口 8282

// 新增加一个属性，用来保存uid到connection的映射(uid是用户id或者客户端唯一标识)
$ws_worker->uidConnections = [];
$ws_worker->pongInterval = 30;  // 设置心跳间隔为 30 秒
$ws_worker->pongTimeout = 55;   // 设置超时限制为 60 秒

// 启动时的回调
$ws_worker->onConnect = function ($connection) {
    $connection->send(json_encode([
                                      'type' => 'connectSuccess',
                                      'message' => '连接成功，id => ' . $connection->id,
                                  ], JSON_UNESCAPED_UNICODE));
};

// 接收到消息时的回调
$ws_worker->onMessage = function ($connection, $data) use ($ws_worker) {
    // 这里使用 use 来将外部的 $ws_worker 引入到回调中
    $messageData = json_decode($data, true);

    var_dump(json_encode($messageData, JSON_UNESCAPED_UNICODE));

    $type = $messageData['type'];
    $user_id = $messageData['user_id'];
    $msg_type = $messageData['msg_type'];
    $duration = $messageData['duration'];
    $url = $messageData['url'];

    global $ws_worker;

    if (!isset($connection->uid)) {
        $connection->uid = $user_id;
        $ws_worker->uidConnections[$user_id] = $connection;
    }

    switch ($type) {
        case 'login':
            // 处理用户登录逻辑
            $ws_worker->uidConnections[$user_id]->send(json_encode([
                                                                       'type' => 'loginSuccess',
                                                                       'message' => '登录成功',
                                                                       'user_id' => $user_id,
                                                                       'time' => time()
                                                                   ], JSON_UNESCAPED_UNICODE));
            break;
        case 'send':
            $to_user_id = $messageData['to_user_id'];
            $content = $messageData['content'];

            // 处理消息发送逻辑
            if (isset($ws_worker->uidConnections[$to_user_id])) {
                $ws_worker->uidConnections[$to_user_id]->send(json_encode([
                                                                              'type' => 'receive',
                                                                              'content' => $content,
                                                                              'user_id' => $user_id,
                                                                              'to_user_id' => $to_user_id,
                                                                              'msg_type' => $msg_type,
                                                                              'duration' => $duration,
                                                                              'url' => $url,
                                                                              'time' => time()
                                                                          ], JSON_UNESCAPED_UNICODE));
            } else {
                echo '对方不在线' . PHP_EOL;
            }
            break;
        case 'pong':
            // 收到客户端的pong响应，更新心跳状态
            $connection->lastPongTime = time();
            break;
        default:
            echo '处理其他类型的消息';
            break;
    }
};

// 设置 WebSocket 客户端的唯一标识
$ws_worker->onWorkerStart = function ($worker) use ($ws_worker) {
    // 定时发送心跳请求
    $worker->timer_id = Timer::add($ws_worker->pongInterval, function () use ($ws_worker) {
        foreach ($ws_worker->uidConnections as $connection) {
            // 如果超过心跳超时限制，关闭连接
            if (isset($connection->lastPongTime) && time() - $connection->lastPongTime > $ws_worker->pongTimeout) {
                echo "关闭连接，用户：{$connection->uid}，心跳超时\n";
                $connection->close();
                unset($ws_worker->uidConnections[$connection->uid]);
            } else {
                // 向客户端发送pong消息
                $connection->send(json_encode([
                                                  'type' => 'pong',
                                                  'time' => time()
                                              ], JSON_UNESCAPED_UNICODE));
            }
        }
    });
};

// 运行 Worker
Worker::runAll();
